package juc;

import org.junit.Test;
import thread.User;

import java.util.HashMap;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

/**
 * @author: feiwang_6
 * @create: 2020/6/22 18:06
 * @description:
 */
public class AtomicTest {
    
    public static void main(String[] args) {
        String str = "123456";
        char[] chars = str.toCharArray();
        for(int i = 0; i < chars.length; i++){
            if("3".equals(chars[i] + "")){
                System.out.println(i);
            }
        }
    }
    
    @Test
    public void intAtomicTest(){
        HashMap<String, Integer> hashMap = new HashMap<>();
        hashMap.get("111");
        
        AtomicInteger atomic = new AtomicInteger(1);
        System.out.println(atomic.addAndGet(10));
        System.out.println(atomic.compareAndSet(10, 11));
        atomic.getAndSet(10);
        atomic.getAndIncrement();
        System.out.println(atomic.get());
        atomic.lazySet(1000);
        AtomicBoolean atomicBoolean = new AtomicBoolean();
    }
    
    @Test
    public void arrayAtomicTest(){
        AtomicIntegerArray array = new AtomicIntegerArray(10);
        array.set(0, 10);
        array.compareAndSet(1, 10, 20);
        System.out.println(array.get(0));
    }
    
    @Test
    public void atomicReferenceTest(){
        AtomicReference<User> atomicUserRef = new AtomicReference<User>();
        User user = new User(15, "ronc");
        atomicUserRef.set(user);
        User updateUser = new User( 17, "Shinichi");
        atomicUserRef.compareAndSet(user, updateUser);
        System.out.println(atomicUserRef.get().getName());
        System.out.println(atomicUserRef.get().getAge());

        AtomicReferenceFieldUpdater<User, String> updater = AtomicReferenceFieldUpdater.
                newUpdater(User.class, String.class, "name");

        updater.compareAndSet(user, "Shinichi", "哈哈哈");
    }
    
    @Test
    public void testFiledUpdate() throws InterruptedException {
        User user = new User(15, "roank");
        AtomicIntegerFieldUpdater<User> updater = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
        updater.addAndGet(user, 10);
        System.out.println(updater.get(user));

        Thread thread = Thread.currentThread();
        System.out.println("1111111111111111111");
        synchronized(user) {
            user.wait(0);
        }
        System.out.println("1111111111111111111");
        //thread.join();
    }
    
    @Test
    public void testCountDownLatch() throws Exception {
        CountDownLatch latch = new CountDownLatch(3);
        new Thread(() -> latch.countDown()).start();
        new Thread(() -> latch.countDown()).start();
        new Thread(() -> latch.countDown()).start();
        
        latch.await();
        
        
        CyclicBarrier barrier = new CyclicBarrier(1);
        barrier.await();
        barrier.await();
        barrier.reset();
        barrier.getNumberWaiting();
    }
    
    @Test
    public void testSemaphore() throws Exception {
        Semaphore semaphore = new Semaphore(3);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    semaphore.acquire();
                    System.out.println("1111111111");
                    Thread.sleep(2000);
                    System.out.println("2222222222");
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        
        for(int i = 0; i < 10; i++){
            new Thread(runnable).start();
        }
        Thread.sleep(10000);
    }
    
    @Test
    public void testExecutor() throws Exception {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
        Runnable runnable = () ->{
            System.out.println("111111111111111 " + System.currentTimeMillis());
        };
        System.out.println("22222222222222222 " + System.currentTimeMillis());
        service.scheduleWithFixedDelay(runnable, 2, 5, TimeUnit.SECONDS);
        Thread.sleep(20000);
        
        FutureTask<Integer> futureTask = new FutureTask<Integer>(() -> 100);
        futureTask.run();
        futureTask.get();
    }
}
